#include "stringutils.h"

#include <QDebug>
#include <QRegularExpression>

// init静态成员变量
QMap<QChar, QChar> StringUtils::s_simplifiedToTraditional;
QMap<QChar, QChar> StringUtils::s_traditionalToSimplified;
bool StringUtils::s_mapInited = false;

QString StringUtils::simplifiedToTraditional(const QString &simplifiedStr)
{
	initSimplifiedTraditionalMap();
	QString ans;
	for (const QChar& c : simplifiedStr) {
		// 有对应的繁体 change ever 原字符
		if (s_simplifiedToTraditional.contains(c)) 	ans.append(s_simplifiedToTraditional.value(c));
		else	ans.append(c);
	}
	return ans;
}

QString StringUtils::traditionalToSimplified(const QString &traditionalStr)
{
	initSimplifiedTraditionalMap();
	QString ans;
	for (const QChar& c : traditionalStr) {
		// 若有对应简体，替换；否则保留原字符
		if (s_traditionalToSimplified.contains(c)) 	ans.append(s_traditionalToSimplified.value(c));
		else	ans.append(c);
	}
	return ans;
}

bool StringUtils::matchFuzzyPinyin(const QString &inputPinyin, const QString &targetPinyin, const QMap<QString, QString> &fuzzyRules)
{
	if (inputPinyin.isEmpty() || targetPinyin.isEmpty())	return false;
	// match all --> true
	if (inputPinyin == targetPinyin)	return true;

	// 模糊音替换
	QString processedInput = inputPinyin;
	for (const auto& rule : fuzzyRules.toStdMap()) {
		// 键值对
		const QString& source = rule.first;
		const QString& target = rule.second;
		processedInput.replace(QRegularExpression(QString("^%1$").arg(source)), target);
	}
	// check again
	return processedInput == targetPinyin;
}

QVector<QString> StringUtils::splitPinyin(const QString &fullPinyin)
{
	QVector<QString> ans;
	QString lowerPinyin = fullPinyin.toLower();

	// 基于拼音韵母来split
	// 韵母list
	const QStringList vowels = {"a", "o", "e", "i", "u", "v", "ai", "ei", "ui", "ao", "ou", "iu", "ie", "ue", "er",
                               "an", "en", "in", "un", "vn", "ang", "eng", "ing", "ong"};

	int curPos = 0;
	int len = lowerPinyin.size();
	
	while (curPos < len) {
		// 匹配2字符韵母 然后1字符
		bool found = false;
		for (int i = 2; i >= 1; i--) {
			if (curPos + i > len)	continue;

			// 子串
			QString subStr = lowerPinyin.mid(curPos, i);
			if (vowels.contains(subStr)) {
				// 声母+韵母 --> 完整拼音
				if (curPos > 0) {
					QString pinyin = lowerPinyin.mid(0, curPos + i);
					ans.append(pinyin);
					// update start pos
					lowerPinyin = lowerPinyin.mid(curPos + 1);
					len = lowerPinyin.size();
					curPos = 0;
					found = true;
					break;
				}
			}
		}
		if (!found)	curPos++;	// 没匹配到下一个
	}
	// 没分割的直接+=
	if (!lowerPinyin.isEmpty())	ans.append(lowerPinyin);
	return ans;
}

bool StringUtils::isChineseChar(const QChar &c)
{
	// 范围
	ushort unicode = c.unicode();
    return (unicode >= 0x4E00 && unicode <= 0x9FA5);
}

bool StringUtils::containsChinese(const QString &str)
{
	// 遍历比较在范围内的
	for (const auto& c  : str) {
		if (isChineseChar(c))	return true;
	}
	return false;
}

// helper
void StringUtils::initSimplifiedTraditionalMap()
{
	if (s_mapInited)	return;

    // change map (charPairs)
    QVector<QPair<QChar, QChar>> charPairs = {
        qMakePair(QChar('学'), QChar('學')), qMakePair(QChar('数'), QChar('數')), 
		qMakePair(QChar('据'), QChar('據')), qMakePair(QChar('码'), QChar('碼')), 
		qMakePair(QChar('论'), QChar('論')),qMakePair(QChar('电'), QChar('電')), 
		qMakePair(QChar('脑'), QChar('腦')), qMakePair(QChar('网'), QChar('網')), 
		qMakePair(QChar('络'), QChar('絡')), qMakePair(QChar('软'), QChar('軟')),
        qMakePair(QChar('件'), QChar('件')), qMakePair(QChar('系'), QChar('系')), 
		qMakePair(QChar('统'), QChar('統')), qMakePair(QChar('开'), QChar('開')), 
		qMakePair(QChar('发'), QChar('發'))
		// ..................... 后续可以拓展 ............................
    };

    // 填充映射表
    for (const auto& pair : charPairs)
    {
        s_simplifiedToTraditional.insert(pair.first, pair.second);
        s_traditionalToSimplified.insert(pair.second, pair.first);
    }

    s_mapInited = true;
    qDebug() << "[StringUtils] 简繁映射表初始化完成，共" << charPairs.size() << "组映射";
	
}
